#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>


//自定义退出码
// char* str_error(size_t pos)
// {
//     char* error_str[] = {"Success","error"};
//     return error_str[pos];
// }

//查看进程的所有退出状态
// int main()
// {
    // for(int i = 0;i<135;++i)
    // {
    //     printf("%d:%s\n",i,strerror(i));
    // }
//     for(int i = 0;i<2;++i)
//     {
//         printf("%d:%s\n",i,str_error(i));
//     }
//     return 0;
// }

//证明exit会释放缓冲区再调用_exit
// int main()
// {
//     printf("Hello Word!");
//     sleep(1);
//     exit(EOF);//验证exit会先刷新缓冲区再返回status退出码
//     return 0;
// }

//证明_exit会直接退出
// int main()
// {
//     printf("Hello Word!");
//     sleep(1);
//     _exit(EOF);//验证_exit会直接退出
//     return 0;
// }

//return调用exit并返回return的值，exit在执行用户的清理函数，冲刷缓冲区，关闭流等后执行_exit

//ls等指令也是程序，执行时也有退出码

//pid_t wait(int*status); 

//查看子进程退出码和信号
// int main()
// {
//     pid_t ret = fork();
//     if(ret == 0)
//     {
//         int i = 5;
//         while(i--)
//         {
//             printf("我是子进程，pid:%d ppid%d,我还剩%d秒\n",getpid(),getppid(),i);
//             sleep(1);
//              //if(i == 1)
//                  //exit(9);
//         }
//     }
//     else
//     {
//         int status = 0;
//         pid_t child = wait(&status);
//         printf("我是父进程,pid:%d ppid:%d,子进程pid:%d 子进程状态码:%d 子进程终止信号:%d\n",getpid(),getppid(),child,(status>>8)&0xFF,status&0x7F);
//     }
//     return 0;
// }

//创建一个运行5秒的子进程exit退出，父进程先等10s查看子进程僵尸状态，wait接收返回值后等待5s后父进程退出
// int main()
// {
//     pid_t ret = fork();
//     if(ret == 0)
//     {
//         int i = 5;
//         while(i--)
//         {
//             printf("我是子进程，pid:%d ppid%d,我还剩%d秒\n",getpid(),getppid(),i);
//             sleep(1);
//         }
//         exit(8);
//     } 
//     int status = 0;
//     sleep(5);
//     pid_t child = wait(&status);
//     printf("我是父进程，pid:%d ppid:%d,子进程pid:%d 子进程状态码:%d 子进程终止信号:%d\n",getpid(),getppid(),child,(status>>8)&0xFF,status&0x7F);
//     sleep(5);
//     return 0;
// }


// int main()
// {
//     pid_t ret = fork();
//     if(ret == 0)
//     {
//         int i = 5;
//         while(i--)
//         {
//             printf("我是子进程，pid:%d ppid%d,我还剩%d秒\n",getpid(),getppid(),i);
//             sleep(1);
//         }
//         exit(8);
//     } 
//     int status = 0;
//     sleep(5);
//     pid_t child = waitpid(ret,&status,WNOHANG);
//     //pid_t child = waitpid(ret,&status,0);
//     printf("我是父进程，pid:%d ppid:%d,子进程pid:%d 子进程状态码:%d 子进程终止信号:%d\n",getpid(),getppid(),child,(status>>8)&0xFF,status&0x7F);
//     sleep(5);
//     return 0;
// }

//验证WNOHANG参数下waitpid将不会等待子进程退出,捕捉异常信号
// int main()
// {
//     pid_t ret = fork();
//     if(ret == 0)
//     {
//         int i = 5;
//         while(i--)
//         {
//             printf("我是子进程，pid:%d ppid%d,我还剩%d秒\n",getpid(),getppid(),i);
//             sleep(1);
//         }
//         int *p = NULL;
//         *p = 1;
//     } 
//     while(1)
//     {
//         int status = 0;
//         pid_t child = waitpid(ret,&status,WNOHANG);
//         printf("我是父进程，pid:%d ppid:%d,子进程pid:%d 子进程状态码:%d 子进程终止信号:%d\n",getpid(),getppid(),child,(status>>8)&0xFF,status&0x7F);
//         if(child == ret)
//             break;

//         sleep(1);
//     }
//     return 0;
// }

//kill -9 信号干掉子进程查看父进程状态
int main()
{
    pid_t ret = fork();
    if(ret == 0)
    {
        while(1)
        {
            printf("我是子进程，pid:%d ppid%d\n",getpid(),getppid());
            sleep(1);
        }
    } 
    while(1)
    {
        int status = 0;
        pid_t child = waitpid(ret,&status,WNOHANG);
        printf("我是父进程，pid:%d ppid:%d,子进程pid:%d 子进程状态码:%d 子进程终止信号:%d\n",getpid(),getppid(),child,(status>>8)&0xFF,status&0x7F);
        if(child == ret)
            break;

        sleep(1);
    }
    return 0;
}





//代码以及本次执行目标
// ls或其他指令执行失败的退出码
// 创建一个运行5秒的子进程exit退出，父进程wait接收返回值
// 创建一个运行5秒的子进程exit退出，父进程先等10s查看子进程僵尸状态，wait接收返回值后等待5s后父进程退出
// 取出status的退出码和终止信号
// 写*NULL异常退出捕获信号，野指针问题捕捉信号，手动干掉进程测试信号
// WONHANG测试